package com.ukefu.webim.web.handler.apps.workorders;

import static org.elasticsearch.index.query.QueryBuilders.termQuery;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.jsoup.Jsoup;
import org.snaker.engine.SnakerEngineFacets;
import org.snaker.engine.access.QueryFilter;
import org.snaker.engine.entity.Task;
import org.snaker.engine.entity.WorkItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.ukefu.core.UKDataContext;
import com.ukefu.util.Menu;
import com.ukefu.util.UKTools;
import com.ukefu.webim.service.es.ContactsRepository;
import com.ukefu.webim.service.es.FavoritesRepository;
import com.ukefu.webim.service.es.OrdersCommentRepository;
import com.ukefu.webim.service.es.WorkOrdersRepository;
import com.ukefu.webim.service.impl.WorkOrdersSendMailService;
import com.ukefu.webim.service.repository.AgentServiceRepository;
import com.ukefu.webim.service.repository.AgentUserContactsRepository;
import com.ukefu.webim.service.repository.AttachmentRepository;
import com.ukefu.webim.service.repository.ChatMessageRepository;
import com.ukefu.webim.service.repository.DataEventRepository;
import com.ukefu.webim.service.repository.MetadataRepository;
import com.ukefu.webim.service.repository.OrganRepository;
import com.ukefu.webim.service.repository.OrgiSkillRelRepository;
import com.ukefu.webim.service.repository.PropertiesEventRepository;
import com.ukefu.webim.service.repository.TagRepository;
import com.ukefu.webim.service.repository.UserRepository;
import com.ukefu.webim.service.repository.WorkOrderTypeRepository;
import com.ukefu.webim.util.PropertiesEventUtils;
import com.ukefu.webim.util.WorkOrdersUtils;
import com.ukefu.webim.util.server.message.ChatMessage;
import com.ukefu.webim.web.handler.Handler;
import com.ukefu.webim.web.model.AgentService;
import com.ukefu.webim.web.model.AgentUserContacts;
import com.ukefu.webim.web.model.AttachmentFile;
import com.ukefu.webim.web.model.Contacts;
import com.ukefu.webim.web.model.DataEvent;
import com.ukefu.webim.web.model.Favorites;
import com.ukefu.webim.web.model.OrdersComment;
import com.ukefu.webim.web.model.Organ;
import com.ukefu.webim.web.model.OrgiSkillRel;
import com.ukefu.webim.web.model.PropertiesEvent;
import com.ukefu.webim.web.model.SysDic;
import com.ukefu.webim.web.model.UKeFuDic;
import com.ukefu.webim.web.model.User;
import com.ukefu.webim.web.model.WorkOrderType;
import com.ukefu.webim.web.model.WorkOrders;

import freemarker.template.TemplateException;

@Controller
@RequestMapping("/apps/workorders")
public class WorkOrdersController extends Handler{
	
	@Autowired
	private WorkOrdersRepository workOrdersRes ;
	
	@Autowired
	private OrdersCommentRepository ordersCommentRes ;
	
	@Autowired
	private ContactsRepository contactsRes ;
	
	@Autowired
	private PropertiesEventRepository propertiesEventRes ;
	
	@Autowired
	private AgentServiceRepository agentServiceRepository;
	
	@Autowired
	private DataEventRepository dataEventRes ;
	
	@Autowired
	private AgentUserContactsRepository agentUserContactsRes; 
	

	@Autowired
	private ChatMessageRepository chatMessageRepository ;
	
	@Autowired
	private TagRepository tagRes ;
	
	@Autowired
	private UserRepository userRes ;
	
	@Autowired
	private OrganRepository organRes ;
	
	@Autowired
	private SnakerEngineFacets facets;
	
	@Autowired
	private AttachmentRepository attachementRes;
	
	@Autowired
	private FavoritesRepository favRes ;
	
	@Autowired
	private WorkOrderTypeRepository workOrderTypeRes ;
	
	@Autowired
	private WorkOrdersSendMailService workOrdersSendMailService;
	@Autowired
	private OrgiSkillRelRepository orgiSkillRelService;
	
	@Autowired
	private MetadataRepository metadataRes;
	
	@Value("${web.upload-path}")
    private String path;
	
	/**
	 * 工单管理-首页-工单概况
	 * @param map
	 * @param request
	 * @param q
	 * @param ckind
	 * @param msg
	 * @return
	 */
    @RequestMapping("/index")
    @Menu(type = "workorders" , subtype = "index" , access = false)
    public ModelAndView index(ModelMap map , HttpServletRequest request , @Valid String q , @Valid String ckind , @Valid String msg) {
    	BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    	if(!StringUtils.isBlank(q)){
        	map.put("q", q) ;
        }
    	if(!StringUtils.isBlank(ckind)){
    		boolQueryBuilder.must(termQuery("ckind" , ckind)) ;
        	map.put("ckind", ckind) ;
        }
    	BoolQueryBuilder myBuilder = QueryBuilders.boolQuery();
    	myBuilder.must(termQuery("orgi" , super.getOrgi(request)));
    	
    	Page<WorkOrders> workOrdersNum = workOrdersRes.countById(myBuilder, null  , false , null, 0, 30,null) ;
    	
    	BoolQueryBuilder unclosed = QueryBuilders.boolQuery();
    	unclosed.mustNot(QueryBuilders.termQuery("status", UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	unclosed.must(termQuery("orgi" , super.getOrgi(request))) ;
    	
    	BoolQueryBuilder accBuilder = QueryBuilders.boolQuery();
    	if(!org.apache.commons.lang3.StringUtils.isBlank(super.getUser(request).getOrgan())) {
    		accBuilder.should(termQuery("accdept" , super.getUser(request).getOrgan()));//受理部门
    	}
    	accBuilder.should(termQuery("accuser" , super.getUser(request).getId()));//受理人
    	accBuilder.should(termQuery("creater" , super.getUser(request).getId()));//工单创建人
    	unclosed.must(accBuilder) ;
    	
    	Page<WorkOrders> unclosedOrders = workOrdersRes.countById(unclosed, null  , false , null, 0, 30,null) ;
    	
    	BoolQueryBuilder my = QueryBuilders.boolQuery();
    	my.must(QueryBuilders.termQuery("creater", super.getUser(request).getId())) ;
    	my.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	my.must(termQuery("orgi" , super.getOrgi(request))) ;
    	Page<WorkOrders> myOrders = workOrdersRes.countById(my, null  , false , null, 0, 30,null) ;
    	
    	BoolQueryBuilder workitem = QueryBuilders.boolQuery();
    	workitem.must(QueryBuilders.termQuery("accuser", super.getUser(request).getId())) ;
    	workitem.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	workitem.must(termQuery("orgi" , super.getOrgi(request))) ;
    	Page<WorkOrders> workitemOrders = workOrdersRes.countById(workitem, null , false , null, 0, 30,null) ;
    	
    	
    	
    	BoolQueryBuilder status = QueryBuilders.boolQuery();
//    	status.must(QueryBuilders.termQuery("accuser", super.getUser(request).getId())) ;
    	status.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	status.must(termQuery("orgi" , super.getOrgi(request))) ;
    	Page<WorkOrders> statusOrders = workOrdersRes.countById(status, "status"  , false , null, 0, 30,null) ;
    	
    	BoolQueryBuilder wotype = QueryBuilders.boolQuery();
//    	wotype.must(QueryBuilders.termQuery("accuser", super.getUser(request).getId())) ;
    	wotype.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	wotype.must(termQuery("orgi" , super.getOrgi(request))) ;
    	Page<WorkOrders> wotypeOrders = workOrdersRes.countById(wotype, "wotype"  , false , null, 0, 30,null) ;
    	
    	map.addAttribute("total", workOrdersNum.getTotalElements()) ;
    	map.addAttribute("unclosed", unclosedOrders.getTotalElements()) ;
    	map.addAttribute("my", myOrders.getTotalElements()) ;
    	map.addAttribute("workitem", workitemOrders.getTotalElements()) ;
    	
    	map.addAttribute("statusOrders", statusOrders) ;
    	map.addAttribute("wotypeOrders", wotypeOrders) ;
    	if(!StringUtils.isBlank(msg)){
    		map.addAttribute("msg", msg) ;
    	}
    	
    	
    	BoolQueryBuilder workItemBoolQueryBuilder = QueryBuilders.boolQuery();
    	
    	BoolQueryBuilder workItemBuilder = QueryBuilders.boolQuery();
    	workItemBuilder.should(termQuery("accuser" , super.getUser(request).getId())) ;
    	workItemBoolQueryBuilder.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	
    	workItemBoolQueryBuilder.must(workItemBuilder) ;
    	workItemBoolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request))) ;
    	org.springframework.data.domain.Page<WorkOrders> page = workOrdersRes.findByCreater(workItemBoolQueryBuilder, false  , false , q, super.getUser(request).getId(),  new PageRequest(super.getP(request), super.getPs(request))) ;
    	map.addAttribute("workOrdersList", page);
    	
    	map.addAttribute("workOrderTypeList", workOrderTypeRes.findByOrgi(super.getOrgi(request))) ;
    	
    	/**
    	 * 统计
    	 */
    	countWorkOrder(map, request);
    	return request(super.createAppsTempletResponse("/apps/business/workorders/index"));
    }
    
    /**
     * 查询指定工单回复
     * @param workOrders
     * @param request
     * @return
     */
    public Page<OrdersComment> getCommentList(WorkOrders workOrders , HttpServletRequest request ){
    	BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    	
    	BoolQueryBuilder myBuilder = QueryBuilders.boolQuery();
    	myBuilder.must(termQuery("dataid" , workOrders.getId())) ;
    	myBuilder.must(termQuery("orgi" , super.getOrgi(request))) ;
    	
    	boolQueryBuilder.must(myBuilder) ;
    	
    	return ordersCommentRes.findByQuery(boolQueryBuilder, null , new PageRequest(super.getP(request), super.getPs(request) , Direction.DESC , "createtime"));
    }
    
    /**
     * 查询部门
     * @param request
     * @return
     */
    private List<Organ> getOrgans(HttpServletRequest request){
    	List<Organ> list = null;
    	if(super.isTenantshare()) {
			List<String> organIdList = new ArrayList<>();
			List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelService.findByOrgi(super.getOrgi(request)) ;
			if(!orgiSkillRelList.isEmpty()) {
				for(OrgiSkillRel rel:orgiSkillRelList) {
					organIdList.add(rel.getSkillid());
				}
			}
			list = organRes.findByIdInAndOrgi(organIdList,super.getOrgi(request));
		}else {
			list = organRes.findByOrgiAndOrgid(super.getOrgi(request),super.getOrgid(request)) ;
		}
    	return list;
    }
    
    /**
     * 查询指定部门下的用户
     * @param request
     * @return
     */
    private Page<User> getUsers(HttpServletRequest request){
    	Page<User> list = null;
    	if(super.isTenantshare()) {
			List<String> organIdList = new ArrayList<>();
			List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelService.findByOrgi(super.getOrgi(request)) ;
			if(!orgiSkillRelList.isEmpty()) {
				for(OrgiSkillRel rel:orgiSkillRelList) {
					organIdList.add(rel.getSkillid());
				}
			}
			list = userRes.findByOrganInAndDatastatusAndOrgi(organIdList,false ,super.getOrgi(request), new PageRequest(0, 10));
		}else {
			list = userRes.findByOrgiAndDatastatus(super.getOrgi(request),false, new PageRequest(0, 10)) ;
		}
    	return list;
    }
    /**
     * 关注工单列表
     * @param map
     * @param request
     * @param q
     * @return
     */
    @RequestMapping("/favorites")
    @Menu(type = "workorders" , subtype = "favorites" , access = false)
    public ModelAndView favorites(ModelMap map , HttpServletRequest request , @Valid String q) {
    	
    	BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    	
    	boolQueryBuilder.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	boolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request)));
    	if(!StringUtils.isBlank(q)){
        	map.put("q", q) ;
        }
    	
    	map.addAttribute("organList", getOrgans(request)) ;
    	org.springframework.data.domain.Page<WorkOrders> page = workOrdersRes.findByCreater(boolQueryBuilder, true , false, q, super.getUser(request).getId(),  new PageRequest(super.getP(request), super.getPs(request))) ;
    	map.addAttribute("workOrdersList", page);
    	if(page.getContent().size()>0){
    		WorkOrders workOrders = page.getContent().get(0) ;
    		
    		if(!StringUtils.isBlank(workOrders.getAccdept())){
    			map.addAttribute("userList", userRes.findByOrganAndDatastatusAndOrgi(workOrders.getAccdept() , false , super.getOrgiByTenantshare(request))) ;
    		}
    		
    		workOrders.setUser(userRes.findByIdAndOrgi(workOrders.getCreater() , super.getOrgiByTenantshare(request)));
    		
    		if(!StringUtils.isBlank(workOrders.getInitiator())){
    			map.addAttribute("initiator", userRes.findByIdAndOrgi(workOrders.getInitiator(),super.getOrgi(request)));
    		}
    		
    		
    		map.addAttribute("workOrders", workOrders);
    	}
    	/**
    	 * 统计
    	 */
    	countWorkOrder(map, request);
    	return request(super.createAppsTempletResponse("/apps/business/workorders/favorites/index"));
    }
    
    /**
     * 关注的工单-详情
     * @param map
     * @param request
     * @param id
     * @return
     */
    @RequestMapping("/favorites/detail")
    @Menu(type = "workorders" , subtype = "favorites" , access = false)
    public ModelAndView favoritesdetail(ModelMap map , HttpServletRequest request , @Valid String id) {
    	workOrderDetail(map, request, id);
    	return request(super.createAppsTempletResponse("/apps/business/workorders/favorites/detail"));
    }
    
    /**
     * 关注的工单-工单回复保存
     * @param map
     * @param request
     * @param id
     * @param comment
     * @param files
     * @return
     * @throws IOException
     * @throws TemplateException
     */
    @RequestMapping("/favorites/save")
    @Menu(type = "workorders" , subtype = "favoritessave" , access = false)
    public ModelAndView favoritessave(ModelMap map , HttpServletRequest request , @Valid String id ,@Valid OrdersComment comment  , @RequestParam(value = "files", required = false) MultipartFile[] files) throws IOException, TemplateException {
    	
    	WorkOrders workOrders = workOrdersRes.findByIdAndOrgi(id,super.getOrgi(request)) ;
    	if(workOrders!=null && comment!=null && !StringUtils.isBlank(comment.getContent())){
    		comment.setId(UKTools.getUUID());
    		comment.setCreater(super.getUser(request).getId());
    		comment.setOrgi(super.getOrgi(request));
    		if(!StringUtils.isBlank(comment.getDataid())){
    			comment.setDataid(id);
    		}
    		comment.setCreatetime(new Date());
    		ordersCommentRes.save(comment) ;
    		
    		/**
    		 * 数据变更记录
    		 */
    		DataEvent event = new DataEvent();
    		event.setDataid(workOrders.getId());
			event.setCreater(super.getUser(request).getId());
			event.setOrgi(super.getOrgi(request));
			event.setModifyid(UKTools.genID());
			event.setCreatetime(new Date());
        	event.setCreatetime(new Date());
        	event.setName("comment");
        	
        	String text = comment.getContent();
        	if(text.length() > 200){
        		event.setContent(text.substring(0, 200));
        	}else if(text.length() > 0){
        		event.setContent(text);
        	}
        	
        	processAttachmentFile(files, workOrders, request, comment.getId(), workOrders.getId());
        	
        	dataEventRes.save(event) ;
        	//变更发送邮件
    		workOrdersSendMailService.sendUpdateWorkOrdersMail(workOrders);
    	}
    	return request(super.createRequestPageTempletResponse("redirect:/apps/workorders/favorites/detail.html?id="+id));
    }
    /**
     * 我的待办工单列表，通过工作流引擎查找方式获取
     * @param map
     * @param request
     * @param q
     * @return
     */
    @RequestMapping("/workflow")
    @Menu(type = "workorders" , subtype = "workflow" , access = false)
    public ModelAndView workitem(ModelMap map , HttpServletRequest request , @Valid String q) {
    	org.snaker.engine.access.Page<WorkItem> wfpage = new org.snaker.engine.access.Page<WorkItem>(super.getPs(request));
		wfpage.setPageNo(super.getP(request));
		List<WorkItem> workItems = facets.getEngine().query().getWorkItems(wfpage, new QueryFilter().setProcessType(UKDataContext.BpmType.WORKORDERS.toString()).setOperators(new String[]{super.getUser(request).getId() , super.getUser(request).getOrgan()})) ;

		map.put("wfpage", wfpage) ;
		if(!StringUtils.isBlank(q)){
        	map.put("q", q) ;
        }
    	map.addAttribute("organList", getOrgans(request)) ;
    	List<String> ids = new ArrayList<String>();
    	for(WorkItem item : workItems){
    		ids.add((String) item.getTaskVariableMap().get("id")) ;
    	}
    	if(ids.size()>0){
	    	Iterable<WorkOrders> tempWorkOrders = workOrdersRes.findByIdInAndOrgi(ids,super.getOrgi(request)) ;
	    	Iterator<WorkOrders> iterator = tempWorkOrders.iterator() ;
	    	List<WorkOrders> workOrdersList = new ArrayList<WorkOrders>();
	    	WorkOrders workOrders = null;
	    	if(iterator.hasNext()){
	    		while(iterator.hasNext()){
	    			workOrdersList.add(workOrders = iterator.next()) ;
	    			for(WorkItem item : workItems){
	    	    		String paramid = ((String) item.getTaskVariableMap().get("id")) ;
	    	    		if(paramid.equals(workOrders.getId())){
	    	    			workOrders.setTaskid(item.getTaskId());
	    	    			workOrders.setOrderid(item.getOrderId());
	    	    		}
	    	    	}
	    		}
	    		
	    		if(!StringUtils.isBlank(workOrders.getAccdept())){
	    			map.addAttribute("userList", userRes.findByOrganAndDatastatusAndOrgi(workOrders.getAccdept() , false , super.getOrgiByTenantshare(request))) ;
	    		}
	    		WorkOrdersUtils.processWorkOrders(workOrdersList, userRes, contactsRes);
	    		workOrders.setUser(userRes.findByIdAndOrgi(workOrders.getCreater() , super.getOrgiByTenantshare(request)));
	    		
	    		if(!StringUtils.isBlank(workOrders.getInitiator())){
	    			map.addAttribute("initiator", userRes.findByIdAndOrgi(workOrders.getInitiator(),super.getOrgi(request)));
	    		}
	    		
	    		map.addAttribute("workOrders", workOrders);
	    	}
	    	
	    	map.addAttribute("workOrdersList",workOrdersList);
	    	
	    }
    	/**
    	 * 统计
    	 */
    	countWorkOrder(map, request);
    	return request(super.createAppsTempletResponse("/apps/business/workorders/workflow/index"));
    }
    /**
     * 工单-待办任务
     * @param map
     * @param request
     * @param id
     * @param orderid
     * @param taskid
     * @return
     */
    @RequestMapping("/workflow/detail")
    @Menu(type = "workorders" , subtype = "workflow" , access = false)
    public ModelAndView workflowdetail(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String orderid ,@Valid String taskid) {
    	ModelAndView view = request(super.createAppsTempletResponse("/apps/business/workorders/workflow/detail"));
    	workOrderDetail(map, request, id);
    	if(!StringUtils.isBlank(taskid)){
    		Task task = facets.getEngine().query().getTask(taskid);
    		if(task!=null){
	    		map.addAttribute("task", task) ;
	    		map.addAttribute("action", task.getActionUrl()) ;
	    		if(task.getActionUrl()!=null && !StringUtils.isBlank(task.getActionUrl())){
	    			if(task.getActionUrl().equals("edit")){
	    				view = request(super.createAppsTempletResponse("/apps/business/workorders/workflow/taskedit"));
	    			}
	    		}
    		}
    	}
    	return view;
    }
    
    /**
     * 工单-待办任务-保存
     * @param map
     * @param request
     * @param id
     * @param comment
     * @param taskid
     * @param orderid
     * @param files
     * @return
     * @throws IOException
     * @throws TemplateException
     */
    @RequestMapping("/workflow/save")
    @Menu(type = "workorders" , subtype = "workflow" , access = false)
    public ModelAndView workflowsave(ModelMap map , HttpServletRequest request , @Valid String id ,@Valid OrdersComment comment ,@Valid String taskid, @Valid String orderid , @RequestParam(value = "files", required = false) MultipartFile[] files) throws IOException, TemplateException {
    	
    	WorkOrders workOrders = workOrdersRes.findByIdAndOrgi(id,super.getOrgi(request)) ;
    	if(workOrders!=null && comment!=null && !StringUtils.isBlank(comment.getContent())){
    		comment.setId(UKTools.getUUID());
    		comment.setCreater(super.getUser(request).getId());
    		comment.setOrgi(super.getOrgi(request));
    		if(!StringUtils.isBlank(comment.getDataid())){
    			comment.setDataid(id);
    		}
    		comment.setCreatetime(new Date());
    		comment.setOptimal(true);	//流程更新
    		ordersCommentRes.save(comment) ;
    		
    		/**
    		 * 数据变更记录
    		 */
    		DataEvent event = new DataEvent();
    		event.setDataid(workOrders.getId());
			event.setCreater(super.getUser(request).getId());
			event.setOrgi(super.getOrgi(request));
			event.setModifyid(UKTools.genID());
			event.setCreatetime(new Date());
        	event.setCreatetime(new Date());
        	event.setName("comment");
        	
        	String text = Jsoup.parse(comment.getContent()).text() ;
        	if(text.length() > 200){
        		event.setContent(text.substring(0, 200));
        	}else if(text.length() > 0){
        		event.setContent(text);
        	}
        	
        	processAttachmentFile(files, workOrders, request, comment.getId(), workOrders.getId());
        	
        	dataEventRes.save(event) ;
        	//变更发送邮件
    		workOrdersSendMailService.sendUpdateWorkOrdersMail(workOrders);
    	}
    	if(!StringUtils.isBlank(taskid)){
    		facets.getEngine().executeTask(taskid, super.getUser(request).getId() , super.getUser(request).getOrgan() , WorkOrdersUtils.updateWorkflowParam(super.getUser(request), workOrders, metadataRes.findByTablenameIgnoreCase(UKDataContext.MetadataTableType.UK_WORKORDERS.toString()))) ;
    	}
    	return request(super.createRequestPageTempletResponse("redirect:/apps/workorders/workflow.html"));
    }
    
    /**
     * 工单-待办任务编辑-保存
     * @param request
     * @param workOrders
     * @param id
     * @param comment
     * @param taskid
     * @param orderid
     * @return
     * @throws IOException
     * @throws TemplateException
     */
    @RequestMapping("/workflow/process")
    @Menu(type = "workorders" , subtype = "workflow" , access = false)
    public ModelAndView workflowprocess(HttpServletRequest request ,@Valid WorkOrders workOrders , @Valid String id ,@Valid OrdersComment comment,@Valid String taskid, @Valid String orderid) throws IOException, TemplateException {
    	WorkOrders tempWorkOrders = workOrdersRes.findByIdAndOrgi(workOrders.getId(),super.getOrgi(request)) ;
    	if(tempWorkOrders!=null){
    		if(comment!=null && !StringUtils.isBlank(comment.getContent())){
	    		comment.setId(UKTools.getUUID());
	    		comment.setCreater(super.getUser(request).getId());
	    		comment.setOrgi(super.getOrgi(request));
	    		if(!StringUtils.isBlank(comment.getDataid())){
	    			comment.setDataid(id);
	    		}
	    		comment.setCreatetime(new Date());
	    		ordersCommentRes.save(comment) ;
	    		
    		}
    		List<PropertiesEvent> events = PropertiesEventUtils.processPropertiesModify(request, workOrders , tempWorkOrders , "id" , "orgi" , "creater" ,"createtime" , "updatetime") ;	//记录 数据变更 历史
	    	if(events.size()>0){
	    		
	    		tempWorkOrders.setAccdept(workOrders.getAccdept());
	    		tempWorkOrders.setAccuser(workOrders.getAccuser());
	    		tempWorkOrders.setPriority(workOrders.getPriority());
	    		tempWorkOrders.setStatus(workOrders.getStatus());
	    		tempWorkOrders.setUpdatetime(new Date());

	    		if(!StringUtils.isBlank(workOrders.getAccuser())){
	    			tempWorkOrders.setAssigned(true);
	    		}else{
	    			tempWorkOrders.setAssigned(false);
	    		}
	    		
		    	workOrdersRes.save(tempWorkOrders) ;
	    		/**
        		 * 数据变更记录
        		 */
        		DataEvent dataEvent = new DataEvent();
        		if(tempWorkOrders.getAccuser()!=null && tempWorkOrders.getAccuser().equals(workOrders.getAccuser())){
            		dataEvent.setEventtype(UKDataContext.WorkOrdersEventType.ACCEPTUSER.toString());
            	}
        		dataEvent.setDataid(workOrders.getId());
    			dataEvent.setCreater(super.getUser(request).getId());
    			dataEvent.setOrgi(super.getOrgi(request));
    			dataEvent.setModifyid(UKTools.genID());
    			dataEvent.setCreatetime(new Date());
            	dataEvent.setCreatetime(new Date());
            	dataEvent.setName("workorders");
            	dataEventRes.save(dataEvent) ;
	    		
	    		Date modifytime = new Date();
	    		for(PropertiesEvent event : events){
	    			event.setDataid(workOrders.getId());
	    			event.setCreater(super.getUser(request).getId());
	    			event.setOrgi(super.getOrgi(request));
	    			event.setModifyid(dataEvent.getId());
	    			event.setCreatetime(modifytime);
	    			if(event.getField().equals("content") && !StringUtils.isBlank(comment.getContent())){
	    				String text = Jsoup.parse(comment.getContent()).text() ;
	    				if(text.length() > 200){
	    					event.setNewvalue(text.substring(0, 200));
	    				}else if(text.length() > 0){
	    					event.setNewvalue(text);
	    				}
	    			}
	    		}
	    		propertiesEventRes.save(events) ;
	    		//变更发送邮件
	    		workOrdersSendMailService.sendUpdateWorkOrdersMail(tempWorkOrders);
	    	}
    	}
    	
    	if(!StringUtils.isBlank(taskid)){
    		facets.getEngine().executeTask(taskid, super.getUser(request).getId() , super.getUser(request).getOrgan(), WorkOrdersUtils.updateWorkflowParam(super.getUser(request), workOrders, metadataRes.findByTablenameIgnoreCase(UKDataContext.MetadataTableType.UK_WORKORDERS.toString()))) ;
    	}
    	
    	return request(super.createRequestPageTempletResponse("redirect:/apps/workorders/workflow.html"));
    }
    
    /**
     * 工单-待办任务-提交保存
     * @param map
     * @param request
     * @param id
     * @param comment
     * @param taskid
     * @param orderid
     * @param files
     * @return
     * @throws IOException
     * @throws TemplateException
     */
    @RequestMapping("/workflow/approval")
    @Menu(type = "workorders" , subtype = "workflow" , access = false)
    public ModelAndView workflowapproval(ModelMap map , HttpServletRequest request , @Valid String id ,@Valid OrdersComment comment ,@Valid String taskid, @Valid String orderid , @RequestParam(value = "files", required = false) MultipartFile[] files) throws IOException, TemplateException {
    	
    	WorkOrders workOrders = workOrdersRes.findByIdAndOrgi(id,super.getOrgi(request)) ;
    	if(workOrders!=null && comment!=null && !StringUtils.isBlank(comment.getContent())){
    		comment.setId(UKTools.getUUID());
    		comment.setCreater(super.getUser(request).getId());
    		comment.setOrgi(super.getOrgi(request));
    		if(!StringUtils.isBlank(comment.getDataid())){
    			comment.setDataid(id);
    		}
    		comment.setCreatetime(new Date());
    		comment.setOptimal(true);	//流程更新
    		comment.setAdmin(true);
    		ordersCommentRes.save(comment) ;
    		
    		/**
    		 * 数据变更记录
    		 */
    		DataEvent event = new DataEvent();
    		event.setDataid(workOrders.getId());
			event.setCreater(super.getUser(request).getId());
			event.setOrgi(super.getOrgi(request));
			event.setModifyid(UKTools.genID());
			event.setCreatetime(new Date());
        	event.setCreatetime(new Date());
        	event.setName("comment");
        	
        	String text = Jsoup.parse(comment.getContent()).text() ;
        	if(text.length() > 200){
        		event.setContent(text.substring(0, 200));
        	}else if(text.length() > 0){
        		event.setContent(text);
        	}
        	
        	processAttachmentFile(files, workOrders, request, comment.getId(), workOrders.getId());
        	
        	dataEventRes.save(event) ;
        	
        	//变更发送邮件
    		workOrdersSendMailService.sendUpdateWorkOrdersMail(workOrders);
    		
        	if(!StringUtils.isBlank(taskid)){
        		/**
        		 * 1、根据审批类型确定 流程流转方式 ： 同意：拒绝：退回：转办
        		 * 2、根据退回方式确定流程的流转方式
        		 */
        		if(!StringUtils.isBlank(comment.getApproval())){
        			switch(comment.getApproval()){
        				case "den" : 
        					//退回到上一个任务节点 ， 如果上一个节点非任务节点，则退回到再上一个节点（只处理一次）
        					facets.getEngine().executeAndJumpTask(taskid, super.getUser(request).getId() , super.getUser(request).getOrgan(), WorkOrdersUtils.updateWorkflowParam(super.getUser(request), workOrders, metadataRes.findByTablenameIgnoreCase(UKDataContext.MetadataTableType.UK_WORKORDERS.toString())), null) ;
        					break ;
        				case "back" :
        					facets.getEngine().executeAndJumpTask(taskid, super.getUser(request).getId() , super.getUser(request).getOrgan(), WorkOrdersUtils.updateWorkflowParam(super.getUser(request), workOrders, metadataRes.findByTablenameIgnoreCase(UKDataContext.MetadataTableType.UK_WORKORDERS.toString())), UKDataContext.START) ;
        					break;
        				case "turn" :
        					boolean turn = false ;
        					if(!StringUtils.isBlank(comment.getAccuser())){
        						facets.getEngine().task().createNewTask(taskid, 0, comment.getAccuser());
        						turn = true ;
        					}else if(!StringUtils.isBlank(comment.getAccdept())){
        						facets.getEngine().task().createNewTask(taskid, 0, comment.getAccdept());
        						turn = true ;
        					}
        					if(turn){
        						facets.getEngine().task().complete(taskid , super.getUser(request).getId() ,  super.getUser(request).getOrgan()) ;
        					}
        					break;
        				default :	//默认处理
        					facets.getEngine().executeTask(taskid, super.getUser(request).getId() , super.getUser(request).getOrgan(), WorkOrdersUtils.updateWorkflowParam(super.getUser(request), workOrders, metadataRes.findByTablenameIgnoreCase(UKDataContext.MetadataTableType.UK_WORKORDERS.toString()))) ;
        					break ;
        			}
        		}
        		
        	}
    	}
    	return request(super.createRequestPageTempletResponse("redirect:/apps/workorders/workflow.html"));
    }
    
    /**
     * 待处理工单-列表
     * @param map
     * @param request
     * @param q
     * @param id
     * @return
     */
    @RequestMapping("/workitem")
    @Menu(type = "workorders" , subtype = "workitem" , access = false)
    public ModelAndView workitem(ModelMap map , HttpServletRequest request , @Valid String q , @Valid String id) {
    	BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    	
    	BoolQueryBuilder myBuilder = QueryBuilders.boolQuery();
    	myBuilder.should(termQuery("accuser" , super.getUser(request).getId())) ;
    	boolQueryBuilder.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	boolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request)));
    	boolQueryBuilder.must(myBuilder) ;
    	
    	if(!StringUtils.isBlank(q)){
        	map.put("q", q) ;
        }
    	map.addAttribute("organList", getOrgans(request)) ;
    	org.springframework.data.domain.Page<WorkOrders> page = workOrdersRes.findByCreater(boolQueryBuilder, false  , false , q, super.getUser(request).getId(),  new PageRequest(super.getP(request), super.getPs(request))) ;
    	map.addAttribute("workOrdersList", page);
    	if(page.getContent().size()>0){
    		WorkOrders workOrders = page.getContent().get(0) ;
    		if(!StringUtils.isBlank(id)){
    			for(WorkOrders tempWorkOrders : page.getContent()){
    				if(tempWorkOrders.getId().equals(id)){
    					workOrders = tempWorkOrders ; break ; 
    				}
    			}
    		}
    		
    		if(!StringUtils.isBlank(workOrders.getAccdept())){
    			map.addAttribute("userList", userRes.findByOrganAndDatastatusAndOrgi(workOrders.getAccdept() , false , super.getOrgiByTenantshare(request))) ;
    		}
    		
    		workOrders.setUser(userRes.findByIdAndOrgi(workOrders.getCreater() , super.getOrgiByTenantshare(request)));
    		
    		if(!StringUtils.isBlank(workOrders.getInitiator())){
    			map.addAttribute("initiator", userRes.findByIdAndOrgi(workOrders.getInitiator(),super.getOrgi(request)));
    		}
    		
    		
    		map.addAttribute("workOrders", workOrders);
    	}
    	/**
    	 * 统计
    	 */
    	countWorkOrder(map, request);
    	return request(super.createAppsTempletResponse("/apps/business/workorders/workitem/index"));
    }
    
    /**
     * 待处理工单 - 详情
     * @param map
     * @param request
     * @param id
     * @return
     */
    @RequestMapping("/workitem/detail")
    @Menu(type = "workorders" , subtype = "workitem" , access = false)
    public ModelAndView workitemdetail(ModelMap map , HttpServletRequest request , @Valid String id) {
    	
    	workOrderDetail(map, request, id);
    	
    	return request(super.createAppsTempletResponse("/apps/business/workorders/workitem/detail"));
    }
    
    /**
     * 待处理工单-提交保存
     * @param request
     * @param workOrders
     * @param id
     * @param comment
     * @param files
     * @param commentcontent
     * @return
     * @throws IOException
     * @throws TemplateException
     */
    @RequestMapping("/workitem/process")
    @Menu(type = "workorders" , subtype = "update" , access = false)
    public ModelAndView workitemprocess(HttpServletRequest request ,@Valid WorkOrders workOrders , @Valid String id ,@Valid OrdersComment comment, @RequestParam(value = "files", required = false) MultipartFile[] files,@Valid String commentcontent) throws IOException, TemplateException {
    	WorkOrders tempWorkOrders = workOrdersRes.findByIdAndOrgi(workOrders.getId(),super.getOrgi(request)) ;
    	if(tempWorkOrders!=null){
    		if(comment!=null && ((!StringUtils.isBlank(comment.getContent())) || (files!=null && files.length > 0))){
	    		comment.setId(UKTools.getUUID());
	    		comment.setCreater(super.getUser(request).getId());
	    		comment.setOrgi(super.getOrgi(request));
	    		if(!StringUtils.isBlank(comment.getDataid())){
	    			comment.setDataid(id);
	    		}
	    		comment.setCreatetime(new Date());
	    		ordersCommentRes.save(comment) ;
    		}
    		if(!StringUtils.isBlank(workOrders.getAccuser())){
    			workOrders.setAssigned(true);
    		}else{
    			workOrders.setAssigned(false);
    		}
    		List<PropertiesEvent> events = PropertiesEventUtils.processPropertiesModify(request, workOrders , tempWorkOrders , "id" , "orgi" , "creater" ,"createtime" , "updatetime") ;	//记录 数据变更 历史
	    	if(events.size()>0){
	    		workOrders.setUpdatetime(new Date());
	    		workOrders.setContent(tempWorkOrders.getContent());
	    		workOrders.setCreater(tempWorkOrders.getCreater());
	    		workOrders.setCreatetime(tempWorkOrders.getCreatetime());
	    		workOrders.setOrgi(tempWorkOrders.getOrgi());
	    		workOrders.setOrgan(tempWorkOrders.getOrgan());
	    		workOrders.setOrderno(tempWorkOrders.getOrderno());
	    		workOrders.setTitle(tempWorkOrders.getTitle());
	    		
	    		if(!StringUtils.isBlank(workOrders.getAccuser())){
	    			workOrders.setAssigned(true);
	    		}else{
	    			workOrders.setAssigned(false);
	    		}
	    		
		    	workOrdersRes.save(workOrders) ;
		    	
		    	processAttachmentFile(files, tempWorkOrders, request, comment.getId(), workOrders.getId());
	    		
	    		/**
        		 * 数据变更记录
        		 */
	    		DataEvent dataEvent = new DataEvent();
	    		if(tempWorkOrders.getAccuser()!=null && tempWorkOrders.getAccuser().equals(workOrders.getAccuser())){
            		dataEvent.setEventtype(UKDataContext.WorkOrdersEventType.ACCEPTUSER.toString());
            	}
        		dataEvent.setDataid(workOrders.getId());
    			dataEvent.setCreater(super.getUser(request).getId());
    			dataEvent.setOrgi(super.getOrgi(request));
    			dataEvent.setModifyid(UKTools.genID());
    			dataEvent.setCreatetime(new Date());
            	dataEvent.setCreatetime(new Date());
            	dataEvent.setName("workorders");
            	dataEventRes.save(dataEvent) ;
            	
	    		Date modifytime = new Date();
	    		for(PropertiesEvent event : events){
	    			event.setDataid(workOrders.getId());
	    			event.setCreater(super.getUser(request).getId());
	    			event.setOrgi(super.getOrgi(request));
	    			event.setModifyid(dataEvent.getId());
	    			event.setCreatetime(modifytime);
	    			if(event.getField().equals("content") && !StringUtils.isBlank(comment.getContent())){
	    				String text = Jsoup.parse(comment.getContent()).text() ;
	    				if(text.length() > 200){
	    					event.setNewvalue(text.substring(0, 200));
	    				}else if(text.length() > 0){
	    					event.setNewvalue(text);
	    				}
	    			}
	    		}
	    		propertiesEventRes.save(events) ;
				//发送邮件
	    		workOrdersSendMailService.sendUpdateWorkOrdersMail(tempWorkOrders);
	    	}
    	}
    	
    	return request(super.createRequestPageTempletResponse("redirect:/apps/workorders/workitem.html"));
    }
    
    /**
     * 未分配工单-列表
     * @param map
     * @param request
     * @param q
     * @return
     */
    @RequestMapping("/notassigned")
    @Menu(type = "workorders" , subtype = "notassigned" , access = false)
    public ModelAndView notassigned(ModelMap map , HttpServletRequest request , @Valid String q) {
    	BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    	
    	BoolQueryBuilder myBuilder = QueryBuilders.boolQuery();
    	boolQueryBuilder.must(termQuery("assigned" , false)) ;
    	boolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request)));
    	boolQueryBuilder.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	
    	BoolQueryBuilder accBuilder = QueryBuilders.boolQuery();
    	if(!org.apache.commons.lang3.StringUtils.isBlank(super.getUser(request).getOrgan())) {
    		accBuilder.should(termQuery("accdept" , super.getUser(request).getOrgan()));//受理部门
    	}
    	accBuilder.should(termQuery("accuser" , super.getUser(request).getId()));//受理人
    	accBuilder.should(termQuery("creater" , super.getUser(request).getId()));//工单创建人
    	boolQueryBuilder.must(accBuilder) ;
    	
    	boolQueryBuilder.must(myBuilder) ;
    	
    	if(!StringUtils.isBlank(q)){
        	map.put("q", q) ;
        }
    	map.addAttribute("organList", getOrgans(request)) ;
    	org.springframework.data.domain.Page<WorkOrders> page = workOrdersRes.findByCreater(boolQueryBuilder, false  , false , q, super.getUser(request).getId(),  new PageRequest(super.getP(request), super.getPs(request) )) ;
    	map.addAttribute("workOrdersList", page);
    	if(page.getContent().size()>0){
    		WorkOrders workOrders = page.getContent().get(0) ;
    		
    		if(!StringUtils.isBlank(workOrders.getAccdept())){
    			map.addAttribute("userList", userRes.findByOrganAndDatastatusAndOrgi(workOrders.getAccdept() , false , super.getOrgiByTenantshare(request))) ;
    		}
    		
    		workOrders.setUser(userRes.findByIdAndOrgi(workOrders.getCreater() , super.getOrgiByTenantshare(request)));
    		
    		if(!StringUtils.isBlank(workOrders.getInitiator())){
    			map.addAttribute("initiator", userRes.findByIdAndOrgi(workOrders.getInitiator(),super.getOrgi(request)));
    		}
    		
    		
    		map.addAttribute("workOrders", workOrders);
    	}
    	/**
    	 * 统计
    	 */
    	countWorkOrder(map, request);
    	return request(super.createAppsTempletResponse("/apps/business/workorders/notassigned/index"));
    }
    
    /**
     * 未分配工单-详情
     * @param map
     * @param request
     * @param id
     * @return
     */
    @RequestMapping("/notassigned/detail")
    @Menu(type = "workorders" , subtype = "notassigned" , access = false)
    public ModelAndView notassigneddetail(ModelMap map , HttpServletRequest request , @Valid String id) {
    	workOrderDetail(map, request, id);
    	return request(super.createAppsTempletResponse("/apps/business/workorders/notassigned/detail"));
    }
    
    /**
     * 未分配工单-提交保存
     * @param request
     * @param workOrders
     * @param id
     * @param comment
     * @return
     * @throws IOException
     * @throws TemplateException
     */
    @RequestMapping("/notassigned/process")
    @Menu(type = "workorders" , subtype = "notassigned" , access = false)
    public ModelAndView notassignedprocess(HttpServletRequest request ,@Valid WorkOrders workOrders , @Valid String id ,@Valid OrdersComment comment) throws IOException, TemplateException {
    	WorkOrders tempWorkOrders = workOrdersRes.findByIdAndOrgi(workOrders.getId(),super.getOrgi(request)) ;
    	if(tempWorkOrders!=null){
    		if(comment!=null && !StringUtils.isBlank(comment.getContent())){
	    		comment.setId(UKTools.getUUID());
	    		comment.setCreater(super.getUser(request).getId());
	    		comment.setOrgi(super.getOrgi(request));
	    		if(!StringUtils.isBlank(comment.getDataid())){
	    			comment.setDataid(id);
	    		}
	    		comment.setCreatetime(new Date());
	    		ordersCommentRes.save(comment) ;
	    		
    		}
    		if(!StringUtils.isBlank(workOrders.getAccuser())){
    			workOrders.setAssigned(true);
    		}else{
    			workOrders.setAssigned(false);
    		}
    		List<PropertiesEvent> events = PropertiesEventUtils.processPropertiesModify(request, workOrders , tempWorkOrders , "id" , "orgi" , "creater" ,"createtime" , "updatetime") ;	//记录 数据变更 历史
	    	if(events.size()>0){
	    		
	    		tempWorkOrders.setAccdept(workOrders.getAccdept());
	    		tempWorkOrders.setAccuser(workOrders.getAccuser());
	    		tempWorkOrders.setPriority(workOrders.getPriority());
	    		tempWorkOrders.setStatus(workOrders.getStatus());
	    		tempWorkOrders.setUpdatetime(new Date());

	    		if(!StringUtils.isBlank(workOrders.getAccuser())){
	    			tempWorkOrders.setAssigned(true);
	    		}else{
	    			tempWorkOrders.setAssigned(false);
	    		}
	    		
	    		if (!StringUtils.isBlank(tempWorkOrders.getAccuser())) {
	        		List<SysDic> statuslist = UKeFuDic.getInstance().getDic("com.dic.workorders.status");
	        		if (statuslist != null && statuslist.size() > 0) {
	        			for(SysDic dic :statuslist) {
	        				if ("处理中".equals(dic.getName())) {
	        					tempWorkOrders.setStatus(dic.getId());
	        					break;
	    					}
	        			}
	    			}
	    		}
	    		
		    	workOrdersRes.save(tempWorkOrders) ;
	    		/**
        		 * 数据变更记录
        		 */
        		DataEvent dataEvent = new DataEvent();
        		if(tempWorkOrders.getAccuser()!=null && tempWorkOrders.getAccuser().equals(workOrders.getAccuser())){
            		dataEvent.setEventtype(UKDataContext.WorkOrdersEventType.ACCEPTUSER.toString());
            	}
        		dataEvent.setDataid(workOrders.getId());
    			dataEvent.setCreater(super.getUser(request).getId());
    			dataEvent.setOrgi(super.getOrgi(request));
    			dataEvent.setModifyid(UKTools.genID());
    			dataEvent.setCreatetime(new Date());
            	dataEvent.setCreatetime(new Date());
            	dataEvent.setName("workorders");
            	dataEventRes.save(dataEvent) ;
	    		
	    		Date modifytime = new Date();
	    		for(PropertiesEvent event : events){
	    			event.setDataid(workOrders.getId());
	    			event.setCreater(super.getUser(request).getId());
	    			event.setOrgi(super.getOrgi(request));
	    			event.setModifyid(dataEvent.getId());
	    			event.setCreatetime(modifytime);
	    			if(event.getField().equals("content") && !StringUtils.isBlank(comment.getContent())){
	    				String text = Jsoup.parse(comment.getContent()).text() ;
	    				if(text.length() > 200){
	    					event.setNewvalue(text.substring(0, 200));
	    				}else if(text.length() > 0){
	    					event.setNewvalue(text);
	    				}
	    			}
	    		}
	    		propertiesEventRes.save(events) ;
	    		//变更发送邮件
	    		workOrdersSendMailService.sendUpdateWorkOrdersMail(tempWorkOrders);
	    	}
    	}
    	
    	return request(super.createRequestPageTempletResponse("redirect:/apps/workorders/notassigned.html"));
    }
    
    /**
     * 我的工单
     * @param map
     * @param request
     * @param q
     * @return
     */
    @RequestMapping("/myorders")
    @Menu(type = "workorders" , subtype = "myorders" , access = false)
    public ModelAndView myorders(ModelMap map , HttpServletRequest request , @Valid String q) {
    	BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    	
    	BoolQueryBuilder myBuilder = QueryBuilders.boolQuery();
    	myBuilder.should(termQuery("creater" , super.getUser(request).getId())) ;
//    	myBuilder.should(termQuery("accuser" , super.getUser(request).getId())) ;
    	boolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request)));
    	boolQueryBuilder.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	
    	boolQueryBuilder.must(myBuilder) ;
    	
    	if(!StringUtils.isBlank(q)){
        	map.put("q", q) ;
        }
    	map.addAttribute("organList", getOrgans(request)) ;
    	org.springframework.data.domain.Page<WorkOrders> page = workOrdersRes.findByCreater(boolQueryBuilder, false  , false , q, super.getUser(request).getId() ,  new PageRequest(super.getP(request), super.getPs(request))) ;
    	map.addAttribute("workOrdersList", page);
    	if(page.getContent().size()>0){
    		WorkOrders workOrders = page.getContent().get(0) ;
    		
    		if(!StringUtils.isBlank(workOrders.getAccdept())){
    			map.addAttribute("userList", userRes.findByOrganAndDatastatusAndOrgi(workOrders.getAccdept() , false , super.getOrgiByTenantshare(request))) ;
    		}
    		
    		if(!StringUtils.isBlank(workOrders.getInitiator())){
    			map.addAttribute("initiator", userRes.findByIdAndOrgi(workOrders.getInitiator(),super.getOrgi(request)));
    		}
    		
    		map.addAttribute("workOrders", workOrders);
    	}
    	/**
    	 * 统计
    	 */
    	countWorkOrder(map, request);
    	return request(super.createAppsTempletResponse("/apps/business/workorders/myorders/index"));
    }
    
    /**
     * 已关闭工单
     * @param map
     * @param request
     * @param q
     * @return
     */
    @RequestMapping("/closed")
    @Menu(type = "workorders" , subtype = "closedorders" , access = false)
    public ModelAndView closedorders(ModelMap map , HttpServletRequest request , @Valid String q) {
    	BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    	
    	BoolQueryBuilder myBuilder = QueryBuilders.boolQuery();
    	
    	boolQueryBuilder.must(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	boolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request)));
    	boolQueryBuilder.must(myBuilder) ;
    	
    	if(!StringUtils.isBlank(q)){
        	map.put("q", q) ;
        }
    	map.addAttribute("organList",getOrgans(request)) ;
    	org.springframework.data.domain.Page<WorkOrders> page = workOrdersRes.findByCreater(boolQueryBuilder, false  , false , q, super.getUser(request).getId() ,  new PageRequest(super.getP(request), super.getPs(request))) ;
    	map.addAttribute("workOrdersList", page);
    	if(page.getContent().size()>0){
    		WorkOrders workOrders = page.getContent().get(0) ;
    		
    		if(!StringUtils.isBlank(workOrders.getAccdept())){
    			map.addAttribute("userList", userRes.findByOrganAndDatastatusAndOrgi(workOrders.getAccdept() , false , super.getOrgiByTenantshare(request))) ;
    		}
    		
    		if(!StringUtils.isBlank(workOrders.getInitiator())){
    			map.addAttribute("initiator", userRes.findByIdAndOrgi(workOrders.getInitiator(),super.getOrgi(request)));
    		}
    		
    		map.addAttribute("workOrders", workOrders);
    	}
    	/**
    	 * 统计
    	 */
    	countWorkOrder(map, request);
    	return request(super.createAppsTempletResponse("/apps/business/workorders/closed/index"));
    }
    
    /**
     * 已关闭工单-详情
     * @param map
     * @param request
     * @param id
     * @return
     */
    @RequestMapping("/closed/detail")
    @Menu(type = "workorders" , subtype = "closedorders" , access = false)
    public ModelAndView closeddetail(ModelMap map , HttpServletRequest request , @Valid String id) {
    	workOrderDetail(map, request, id);
    	return request(super.createAppsTempletResponse("/apps/business/workorders/closed/detail"));
    }
    
    /**
     * 已关闭工单 - 提交保存
     * @param map
     * @param request
     * @param id
     * @param comment
     * @param files
     * @return
     * @throws IOException
     * @throws TemplateException
     */
    @RequestMapping("/closed/save")
    @Menu(type = "workorders" , subtype = "closedsave" , access = false)
    public ModelAndView closedsave(ModelMap map , HttpServletRequest request , @Valid String id ,@Valid OrdersComment comment  , @RequestParam(value = "files", required = false) MultipartFile[] files) throws IOException, TemplateException {
    	
    	WorkOrders workOrders = workOrdersRes.findByIdAndOrgi(id,super.getOrgi(request)) ;
    	if(workOrders!=null && comment!=null && !StringUtils.isBlank(comment.getContent())){
    		comment.setId(UKTools.getUUID());
    		comment.setCreater(super.getUser(request).getId());
    		comment.setOrgi(super.getOrgi(request));
    		if(!StringUtils.isBlank(comment.getDataid())){
    			comment.setDataid(id);
    		}
    		comment.setCreatetime(new Date());
    		ordersCommentRes.save(comment) ;
    		
    		/**
    		 * 数据变更记录
    		 */
    		DataEvent event = new DataEvent();
    		event.setDataid(workOrders.getId());
			event.setCreater(super.getUser(request).getId());
			event.setOrgi(super.getOrgi(request));
			event.setModifyid(UKTools.genID());
			event.setCreatetime(new Date());
        	event.setCreatetime(new Date());
        	event.setName("comment");
        	
        	String text = Jsoup.parse(comment.getContent()).text() ;
        	if(text.length() > 200){
        		event.setContent(text.substring(0, 200));
        	}else if(text.length() > 0){
        		event.setContent(text);
        	}
        	
        	processAttachmentFile(files, workOrders, request, comment.getId(), workOrders.getId());
        	
        	dataEventRes.save(event) ;
        	//变更发送邮件
    		workOrdersSendMailService.sendUpdateWorkOrdersMail(workOrders);
    	}
    	return request(super.createRequestPageTempletResponse("redirect:/apps/workorders/closed/detail.html?id="+id));
    }
    
    /**
     * 我的工单-详情
     * @param map
     * @param request
     * @param id
     * @return
     */
    @RequestMapping("/myorders/detail")
    @Menu(type = "workorders" , subtype = "myorders" , access = false)
    public ModelAndView mydetail(ModelMap map , HttpServletRequest request , @Valid String id) {
    	
    	workOrderDetail(map, request, id);
    	return request(super.createAppsTempletResponse("/apps/business/workorders/myorders/detail"));
    }
    
    /**
     * 我的工单-提交保存
     * @param map
     * @param request
     * @param id
     * @param comment
     * @param files
     * @return
     * @throws IOException
     * @throws TemplateException
     */
    @RequestMapping("/myorders/save")
    @Menu(type = "workorders" , subtype = "favoritessave" , access = false)
    public ModelAndView myorderssave(ModelMap map , HttpServletRequest request , @Valid String id ,@Valid OrdersComment comment , @RequestParam(value = "files", required = false) MultipartFile[] files,String status) throws IOException, TemplateException {
    	
    	WorkOrders workOrders = workOrdersRes.findByIdAndOrgi(id,super.getOrgi(request)) ;
    	if(workOrders!=null && comment!=null && !StringUtils.isBlank(comment.getContent())){
    		comment.setCreater(super.getUser(request).getId());
    		comment.setOrgi(super.getOrgi(request));
    		comment.setId(UKTools.getUUID());
    		if(!StringUtils.isBlank(comment.getDataid())){
    			comment.setDataid(id);
    		}
    		comment.setCreatetime(new Date());
    		ordersCommentRes.save(comment) ;
    		
    		processAttachmentFile(files, workOrders, request, comment.getId(), workOrders.getId());
    		
    		if (!StringUtils.isBlank(status)) {
    			workOrders.setStatus(status);
    			workOrders.setUpdatetime(new Date());
    			List<SysDic> statuslist = UKeFuDic.getInstance().getDic("com.dic.workorders.status");
        		if (statuslist != null && statuslist.size() > 0) {
        			for(SysDic dic :statuslist) {
        				if ("重新打开".equals(dic.getName()) && dic.getId().equals(status)) {
        					workOrders.setAssigned(false);
        					workOrders.setAccuser(null);
        					workOrders.setAccdept(null);
        					workOrders.setCurrent(null);
        					workOrders.setCurrentorgan(null);
        					break;
    					}
        			}
    			}
    			workOrdersRes.save(workOrders);
			}
    		
    		
    		/**
    		 * 数据变更记录
    		 */
    		DataEvent event = new DataEvent();
    		event.setDataid(workOrders.getId());
			event.setCreater(super.getUser(request).getId());
			event.setOrgi(super.getOrgi(request));
			event.setModifyid(UKTools.genID());
			event.setCreatetime(new Date());
        	event.setCreatetime(new Date());
        	event.setName("comment");
        	String text = Jsoup.parse(comment.getContent()).text() ;
        	if(text.length() > 200){
        		event.setContent(text.substring(0, 200));
        	}else if(text.length() > 0){
        		event.setContent(text);
        	}
        	
        	dataEventRes.save(event) ;
        	//变更发送邮件
    		workOrdersSendMailService.sendUpdateWorkOrdersMail(workOrders);
    	}
    	return request(super.createRequestPageTempletResponse("redirect:/apps/workorders/myorders/detail.html?id="+id));
    }
    
    /**
     * 保存附件
     * @param files
     * @param workOrders
     * @param request
     * @param dataid
     * @param modelid
     * @throws IOException
     */
    private void  processAttachmentFile(MultipartFile[] files , WorkOrders workOrders, HttpServletRequest request  , String dataid , String modelid) throws IOException{
    	if(files!=null && files.length > 0){
    		boolean attachment = false ;
    		//保存附件
    		for(MultipartFile file : files){
    			if(file.getSize() > 0){			//文件尺寸 限制 ？在 启动 配置中 设置 的最大值，其他地方不做限制
    				String fileid = UKTools.md5(file.getBytes()) ;	//使用 文件的 MD5作为 ID，避免重复上传大文件
    				if(!StringUtils.isBlank(fileid)){
    					attachment = true ;
		    			AttachmentFile attachmentFile = new AttachmentFile() ;
		    			attachmentFile.setCreater(super.getUser(request).getId());
		    			attachmentFile.setOrgi(super.getOrgi(request));
		    			attachmentFile.setOrgan(super.getUser(request).getOrgan());
		    			attachmentFile.setDataid(dataid);
		    			attachmentFile.setModelid(modelid);
		    			attachmentFile.setModel(UKDataContext.ModelType.WORKORDERS.toString());
		    			attachmentFile.setFilelength((int) file.getSize());
		    			if(file.getContentType()!=null && file.getContentType().length() > 255){
		    				attachmentFile.setFiletype(file.getContentType().substring(0 , 255));
		    			}else{
		    				attachmentFile.setFiletype(file.getContentType());
		    			}
		    			if(file.getOriginalFilename()!=null && file.getOriginalFilename().length() > 255){
		    				attachmentFile.setTitle(file.getOriginalFilename().substring(0 , 255));
		    			}else{
		    				attachmentFile.setTitle(file.getOriginalFilename());
		    			}
		    			if(!StringUtils.isBlank(attachmentFile.getFiletype()) && attachmentFile.getFiletype().indexOf("image") >= 0){
		    				attachmentFile.setImage(true);
		    			}
		    			attachmentFile.setFileid(fileid);
		    			attachementRes.save(attachmentFile) ;
		    			FileUtils.writeByteArrayToFile(new File(path , "app/workorders/"+fileid), file.getBytes());
    				}
    			}
    		}
    		workOrders.setAnonymous(attachment);//变更用途为是否有 附件
    	}
    }
    
    /**
     * 工单编辑
     * @param map
     * @param request
     * @param id
     * @return
     */
    @RequestMapping("/edit")
    @Menu(type = "workorders" , subtype = "detail" , access = false)
    public ModelAndView edit(ModelMap map , HttpServletRequest request , @Valid String id) {
    	ModelAndView view = request(super.createAppsTempletResponse("/apps/business/workorders/edit"));
    	WorkOrders workOrders = workOrdersRes.findByIdAndOrgi(id,super.getOrgi(request)) ;
    	if(workOrders!=null && super.getUser(request).getId().equals(workOrders.getCreater())){
    		map.addAttribute("workOrders", workOrders);
    		
    		workOrders.setUser(userRes.findByIdAndOrgi(workOrders.getCreater() , super.getOrgiByTenantshare(request)));
    		
    		if(!StringUtils.isBlank(workOrders.getCusid())){
    			workOrders.setContacts(contactsRes.findByIdAndOrgi(workOrders.getCusid(),super.getOrgi(request)));
    		}
    		
    		if(!StringUtils.isBlank(workOrders.getInitiator())){
    			map.addAttribute("initiator", userRes.findByIdAndOrgi(workOrders.getInitiator(),super.getOrgi(request)));
    		}
    		
    		if(!StringUtils.isBlank(workOrders.getAccdept())){
    			map.addAttribute("userList", userRes.findByOrganAndDatastatusAndOrgi(workOrders.getAccdept() , false , super.getOrgiByTenantshare(request))) ;
    		}
    		map.addAttribute("attachmentFileList", attachementRes.findByModelidAndOrgi(workOrders.getId(), super.getOrgi(request))) ;
    	}else{
    		view = request(super.createRequestPageTempletResponse("redirect:/apps/workorders/myorders.html"));
    	}
    	
    	map.addAttribute("workOrderTypeList", workOrderTypeRes.findByOrgi(super.getOrgi(request))) ;
    	map.addAttribute("tags", tagRes.findByOrgiAndTagtype(super.getOrgi(request) , UKDataContext.ModelType.WORKORDERS.toString())) ;
    	map.addAttribute("organList", getOrgans(request)) ;
    	
    	return view;
    }
    
    /**
     * 工单-新增
     * @param map
     * @param request
     * @return
     */
    @RequestMapping("/add")
    @Menu(type = "workorders" , subtype = "add" , access = false)
    public ModelAndView add(ModelMap map , HttpServletRequest request) {
    	map.addAttribute("userList",getUsers(request)) ;
    	map.addAttribute("tags", tagRes.findByOrgiAndTagtype(super.getOrgi(request) , UKDataContext.ModelType.WORKORDERS.toString())) ;
    	map.addAttribute("organList", getOrgans(request)) ;
    	map.addAttribute("workOrderTypeList", workOrderTypeRes.findByOrgi(super.getOrgi(request))) ;
        return request(super.createAppsTempletResponse("/apps/business/workorders/add"));
    }
    
    @RequestMapping("/fav/order")
    @Menu(type = "workorders" , subtype = "favorder" , access = false)
    public ModelAndView favorder(ModelMap map , HttpServletRequest request , @Valid Favorites fav) {
    	WorkOrders workOrders = workOrdersRes.findByIdAndOrgi(fav.getOrderid(),super.getOrgi(request)) ;
    	if(!StringUtils.isBlank(fav.getOrderid())){
    		List<Favorites> favList = favRes.findByOrderidAndOrgiAndCreater(fav.getOrderid() , super.getOrgi(request),super.getUser(request).getId()) ;
    		if(favList.size() > 0){
    			Favorites f = favList.get(0);
    			if("false".equals(f.getCode())) {
    				f.setCode("true");
    				workOrders.setFav(fav);
    			}else {
    				f.setCode("false");
    			}
    			favRes.save(f);
    		}else{
	    		fav.setOrgi(super.getOrgi(request));
	    		fav.setCreater(super.getUser(request).getId());
	    		fav.setCreatetime(new Date());
	    		fav.setModel(UKDataContext.ModelType.WORKORDERS.toString());
	    		fav.setUsername(super.getUser(request).getUsername());
	    		favRes.save(fav) ;
	    		workOrders.setFav(fav);
    		}
    		map.addAttribute("workOrders" , workOrders) ;
    	}
        return request(super.createRequestPageTempletResponse("/apps/business/workorders/orderno"));
    }
    
    @RequestMapping("/dept/user")
    @Menu(type = "workorders" , subtype = "deptuser" , access = false)
    public ModelAndView add(ModelMap map , HttpServletRequest request , @Valid String dept) {
    	if(!StringUtils.isBlank(dept)){
    		map.addAttribute("userList", userRes.findByOrganAndDatastatusAndOrgi(dept , false , super.getOrgiByTenantshare(request))) ;
    	}
        return request(super.createRequestPageTempletResponse("/apps/business/workorders/deptuser"));
    }
    
    /**
     * 工单新增-保存
     * @param request
     * @param workOrders
     * @param files
     * @return
     * @throws Exception
     */
	@RequestMapping("/save")
    @Menu(type = "workorders" , subtype = "save" , access = false)
    public ModelAndView save(HttpServletRequest request ,@Valid WorkOrders workOrders , @RequestParam(value = "files", required = false) MultipartFile[] files) throws Exception {
    	ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/apps/workorders/index.html")); 
    	workOrders.setOrgi(super.getOrgi(request));
    	workOrders.setCreater(super.getUser(request).getId());
    	workOrders.setUsername(super.getUser(request).getUsername());
    	
    	workOrders.setOrgan(super.getUser(request).getOrgan());

		String orderNo = String.valueOf(WorkOrdersUtils.getWorkOrderNumber(super.getOrgi(request)));
		List<WorkOrders> orderNoList = null;
    	do {
			orderNoList	= workOrdersRes.findByOrdernoAndOrgi(orderNo,super.getOrgi(request));
			if(orderNoList != null && orderNoList.size() > 0){
				orderNo = String.valueOf(WorkOrdersUtils.getWorkOrderNumber(super.getOrgi(request)));
			}
		}while (orderNoList != null && orderNoList.size() > 0);


    	workOrders.setOrderno(orderNo);
    	if(!StringUtils.isBlank(workOrders.getAccuser())){
    		workOrders.setAssigned(true) ;
    	}else{
    		workOrders.setAssigned(false) ;
    	}
    	
    	if (StringUtils.isBlank(workOrders.getStatus()) && !StringUtils.isBlank(workOrders.getAccuser())) {
    		List<SysDic> statuslist = UKeFuDic.getInstance().getDic("com.dic.workorders.status");
    		if (statuslist != null && statuslist.size() > 0) {
    			for(SysDic dic :statuslist) {
    				if ("处理中".equals(dic.getName())) {
    					workOrders.setStatus(dic.getId());
    					break;
					}
    			}
			}
		}
    	
    	processAttachmentFile(files, workOrders, request, workOrders.getId(), workOrders.getId());
    	

    	WorkOrderType workOrderType = workOrderTypeRes.findByIdAndOrgi(workOrders.getWotype(), super.getOrgi(request)) ;
    	if(workOrderType!=null && workOrderType.isBpm() && !StringUtils.isBlank(workOrderType.getProcessid())){
    		WorkOrdersUtils.createProcessInstance(facets , workOrderType , super.getUser(request), workOrders , metadataRes.findByTablenameIgnoreCase(UKDataContext.MetadataTableType.UK_WORKORDERS.toString())) ;
    	}
    	workOrdersRes.save(workOrders) ;
    	
    	//发送工单邮件
    	workOrdersSendMailService.sendCreateWorkOrdersMail(workOrders,super.getUser(request),super.getOrgi(request));
    	return view;
    }
	
	/**
	 * 工单编辑-保存
	 * @param request
	 * @param workOrders
	 * @param files
	 * @return
	 * @throws IOException
	 * @throws TemplateException
	 */
    @RequestMapping("/update/all")
    @Menu(type = "workorders" , subtype = "updateall" , access = false)
    public ModelAndView updateall(HttpServletRequest request ,@Valid WorkOrders workOrders , @RequestParam(value = "files", required = false) MultipartFile[] files) throws IOException, TemplateException {
    	WorkOrders tempWorkOrders = workOrdersRes.findByIdAndOrgi(workOrders.getId(),super.getOrgi(request)) ;
    	if(tempWorkOrders!=null){
    		if(!StringUtils.isBlank(workOrders.getAccuser())){
    			workOrders.setAssigned(true);
    		}else{
    			workOrders.setAssigned(false);
    		}
    		List<PropertiesEvent> events = PropertiesEventUtils.processPropertiesModify(request, workOrders , tempWorkOrders , "id" , "orgi" , "creater" ,"createtime" , "updatetime") ;	//记录 数据变更 历史
	    	if(events.size()>0){
	    		
	    		DataEvent dataEvent = new DataEvent();
	    		if(tempWorkOrders.getAccuser()!=null && tempWorkOrders.getAccuser().equals(workOrders.getAccuser())){
            		dataEvent.setEventtype(UKDataContext.WorkOrdersEventType.ACCEPTUSER.toString());
            	}
        		dataEvent.setDataid(workOrders.getId());
    			dataEvent.setCreater(super.getUser(request).getId());
    			dataEvent.setOrgi(super.getOrgi(request));
    			dataEvent.setModifyid(UKTools.genID());
    			dataEvent.setCreatetime(new Date());
            	dataEvent.setCreatetime(new Date());
            	dataEvent.setName("workorders");
            	dataEventRes.save(dataEvent) ;
	    		
	    		Date modifytime = new Date();
	    		for(PropertiesEvent event : events){
	    			event.setDataid(workOrders.getId());
	    			event.setCreater(super.getUser(request).getId());
	    			event.setOrgi(super.getOrgi(request));
	    			event.setModifyid(dataEvent.getId());
	    			event.setCreatetime(modifytime);
	    		}
	    		propertiesEventRes.save(events) ;
	    		
	    	}
    		if(events.size()>0  || files.length > 0){
    			UKTools.copyProperties(workOrders, tempWorkOrders , "createtime");
    			if(events.size()>0 ) {
    				//发送邮件
    	    		workOrdersSendMailService.sendUpdateWorkOrdersMail(tempWorkOrders);
    			}
    			
	    		tempWorkOrders.setUpdatetime(new Date());
	    		
	    		processAttachmentFile(files, tempWorkOrders, request, workOrders.getId(), workOrders.getId());
	    		
		    	workOrdersRes.save(tempWorkOrders) ;
    		}
    	}
    	
    	return request(super.createRequestPageTempletResponse("redirect:/apps/workorders/myorders.html"));
    }
    
    /**
     * 查询指定工单回复内容
     * @param map
     * @param request
     * @param orderid
     * @return
     */
    @RequestMapping("/comments")
    @Menu(type = "workorders" , subtype = "comments" , access = false)
    public ModelAndView comments(ModelMap map , HttpServletRequest request , @Valid String orderid) {
    	
    	WorkOrders workOrders = workOrdersRes.findByIdAndOrgi(orderid,super.getOrgi(request)) ;
    	if(workOrders!=null){
    		map.addAttribute("orderCommentList", getCommentList(workOrders, request));
    		map.addAttribute("attachmentFileList", attachementRes.findByModelidAndOrgi(workOrders.getId(), super.getOrgi(request))) ;
    		map.addAttribute("workOrders", workOrders) ;
    	}
    	map.addAttribute("organList", getOrgans(request)) ;
    	
    	
    	return request(super.createRequestPageTempletResponse("/apps/business/workorders/comments"));
    }
    
    /**
     * 工单详情-回复记录
     * @param map
     * @param request
     * @param orderid
     * @return
     */
    @RequestMapping("/detail/comments")
    @Menu(type = "workorders" , subtype = "detailcomments" , access = false)
    public ModelAndView detailcomments(ModelMap map , HttpServletRequest request , @Valid String orderid) {
    	
    	WorkOrders workOrders = workOrdersRes.findByIdAndOrgi(orderid,super.getOrgi(request)) ;
    	if(workOrders!=null){
    		map.addAttribute("orderCommentList1", getCommentList(workOrders, request));
    		map.addAttribute("attachmentFileList", attachementRes.findByModelidAndOrgi(workOrders.getId(), super.getOrgi(request))) ;
    		map.addAttribute("workOrders", workOrders) ;
    	}
    	map.addAttribute("organList",getOrgans(request)) ;
    	return request(super.createRequestPageTempletResponse("/apps/business/workorders/detailcomments"));
    }
    
    /**
     * 工单详情-变更记录
     * @param map
     * @param request
     * @param orderid
     * @return
     */
    @RequestMapping("/detail/dataevent")
    @Menu(type = "workorders" , subtype = "dataevent" , access = false)
    public ModelAndView dataevent(ModelMap map , HttpServletRequest request , @Valid String orderid) {
    	
    	WorkOrders workOrders = workOrdersRes.findByIdAndOrgi(orderid,super.getOrgi(request)) ;
    	if(workOrders!=null){
    		map.addAttribute("dataEventList" , dataEventRes.findByDataidAndOrgi(workOrders.getId(), super.getOrgi(request) , new PageRequest(super.getP(request), super.getPs(request) , Direction.DESC , "createtime"))) ;
    	}
    	return request(super.createRequestPageTempletResponse("/apps/business/workorders/detailevent"));
    }
    
    
    @RequestMapping("/pages")
    @Menu(type = "workorders" , subtype = "pages" , access = false)
    public ModelAndView pages(ModelMap map , HttpServletRequest request , @Valid String q , @Valid String tp) {
    	BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    	
    	BoolQueryBuilder myBuilder = QueryBuilders.boolQuery();
    	myBuilder.should(termQuery("accuser" , super.getUser(request).getId())) ;
    	boolQueryBuilder.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	
    	boolQueryBuilder.must(myBuilder) ;
    	
    	if(!StringUtils.isBlank(q)){
        	map.put("q", q) ;
        }
    	if(!StringUtils.isBlank(tp)){
        	map.put("tp", tp) ;
        }
    	map.addAttribute("organList", getOrgans(request)) ;
    	org.springframework.data.domain.Page<WorkOrders> page = workOrdersRes.findByCreater(boolQueryBuilder, false  , false , q, super.getUser(request).getId(),  new PageRequest(super.getP(request), super.getPs(request))) ;
    	map.addAttribute("workOrdersList", page);
    	
    	return request(super.createRequestPageTempletResponse("/apps/business/workorders/workorderspages"));
    }
    
    /**
     * 工单-删除
     * @param request
     * @param id
     * @return
     */
    @RequestMapping("/delete")
    @Menu(type = "workorders" , subtype = "delete" , access = false)
    public ModelAndView delete(HttpServletRequest request ,@Valid String id) {
    	WorkOrders tempWorkOrders = workOrdersRes.findByIdAndOrgi(id,super.getOrgi(request)) ;
    	tempWorkOrders.setDatastatus(true);
    	if(tempWorkOrders.isAssigned() && !StringUtils.isBlank(tempWorkOrders.getBpmid())){
    		facets.getEngine().order().complete(tempWorkOrders.getBpmid());	//结束
    	}
    	workOrdersRes.save(tempWorkOrders) ;
    	
    	return request(super.createRequestPageTempletResponse("redirect:/apps/workorders/myorders.html"));
    }
    
    /**
     * 工单-附件删除
     * @param request
     * @param id
     * @return
     */
    @RequestMapping("/files/delete")
    @Menu(type = "workorders" , subtype = "filesdelete" , access = false)
    public ModelAndView filesdelete(HttpServletRequest request ,@Valid String id) {
    	if(!StringUtils.isBlank(id)){
    		AttachmentFile attachmentFile = attachementRes.findByIdAndOrgi(id, super.getOrgi(request)) ;
    		if(attachmentFile!=null){
    			attachementRes.delete(attachmentFile);
    			FileUtils.deleteQuietly(new File(path , "app/workorders/"+attachmentFile.getFileid())) ;
    		}
    	}
    	return request(super.createRequestPageTempletResponse("/public/success"));
    }
    
    /**
     * 工单-附件添加
     * @param request
     * @param response
     * @param file
     * @return
     * @throws IOException
     */
    @RequestMapping("/upload")
    @Menu(type = "workorders" , subtype = "upload" , access = false)
    public ModelAndView upload(HttpServletRequest request , HttpServletResponse response , @RequestParam(value = "file", required = false) MultipartFile file) throws IOException {
    	ModelAndView view = request(super.createRequestPageTempletResponse("/apps/business/workorders/upload")) ;
    	String imgid = UKTools.getUUID() ;
    	if(file!=null){
	    	FileUtils.writeByteArrayToFile(new File(path , "workorders/"+UKTools.md5(file.getBytes())), file.getBytes());
    	}
    	view.addObject("imgid", imgid) ;
    	view.addObject("name", file.getName()) ;
        return view;
    }
    
    /**
     * 其他地方引用，工单详情
     * @param map
     * @param request
     * @param id
     * @return
     */
    @RequestMapping("/embed/detail")
    @Menu(type = "workorders" , subtype = "embeddetail" , access = false)
    public ModelAndView embeddetail(ModelMap map , HttpServletRequest request , @Valid String id) {
    	
    	workOrderDetail(map, request, id);
    	return request(super.createRequestPageTempletResponse("/apps/business/workorders/embed/detail"));
    }
    
    /**
     * 其他地方引用，工单-新增
     * @param map
     * @param request
     * @param contactsid
     * @param eventid
     * @param ani
     * @param dataid
     * @param source
     * @return
     */
    @RequestMapping("/embed/add")
    @Menu(type = "workorders" , subtype = "add" , access = false)
    public ModelAndView embedadd(ModelMap map , HttpServletRequest request , @Valid String contactsid, @Valid String eventid, @Valid String ani , @Valid String dataid, @Valid String source ,String organ) throws UnsupportedEncodingException {
    	map.addAttribute("userList", getUsers(request)) ;
    	map.addAttribute("tags", tagRes.findByOrgiAndTagtype(super.getOrgi(request) , UKDataContext.ModelType.WORKORDERS.toString())) ;
    	map.addAttribute("organList", getOrgans(request)) ;

		
		map.addAttribute("organ", organ) ;
    	
    	if(!StringUtils.isBlank(source)) {
    		map.addAttribute("source", source) ;
    	}
    	if(!StringUtils.isBlank(ani)) {
    		map.addAttribute("ani", ani) ;
    	}
    	
    	if(!StringUtils.isBlank(contactsid)){
    		map.addAttribute ("contacts", contactsRes.findByIdAndOrgi(contactsid,super.getOrgi(request)));
		}
    	
    	if(!StringUtils.isBlank(dataid)){
    		map.addAttribute ("dataid", dataid);
    		AgentService agentService = agentServiceRepository.findByIdAndOrgi(dataid, super.getOrgi(request)) ;
			if(agentService!=null) {
				Page<ChatMessage> messageList = chatMessageRepository.findByAgentserviceidAndOrgi(agentService.getId(), agentService.getOrgi(), new PageRequest(0, 200, Direction.DESC , "updatetime")) ;
				
				map.addAttribute ("messageList", messageList);
			}
		}
    	if(!StringUtils.isBlank(eventid)){
    		map.addAttribute ("eventid", eventid);
		}
    	
    	map.addAttribute("workOrderTypeList", workOrderTypeRes.findByOrgi(super.getOrgi(request))) ;
        return request(super.createRequestPageTempletResponse("/apps/business/workorders/embed/add"));
    }
    
    /**
     * 其他地方引用，工单-新增保存
     * @param request
     * @param workOrders
     * @param source
     * @param contactsid
     * @param dataid
     * @param name
     * @param ani
     * @param eventid
     * @param files
     * @return
     * @throws FileNotFoundException
     * @throws IOException
     */
    @RequestMapping("/embed/save")
    @Menu(type = "workorders" , subtype = "embedsave" , access = false)
    public ModelAndView embedsave(HttpServletRequest request ,@Valid WorkOrders workOrders , @Valid String source, @Valid String contactsid , @Valid String dataid , @Valid String name, @Valid String ani, @Valid String eventid, @RequestParam(value = "files", required = false) MultipartFile[] files) throws FileNotFoundException, IOException {
    	ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/agent/workorders/list.html?contactsid="+contactsid)) ;
    	workOrders.setOrgi(super.getOrgi(request));
    	workOrders.setCreater(super.getUser(request).getId());
    	workOrders.setUsername(super.getUser(request).getUsername());
    	
    	workOrders.setOrgan(super.getUser(request).getOrgan());
    	if(!StringUtils.isBlank(eventid)) {
    		workOrders.setEventid(eventid);
    	}
    	if(!StringUtils.isBlank(dataid)) {
    		workOrders.setDataid(dataid);
    	}
    	if(!StringUtils.isBlank(contactsid)) {
    		workOrders.setCusid(contactsid);
    	}else if(!StringUtils.isBlank(name)){
    		Contacts contacts = new Contacts();
    		contacts.setName(name);
    		if(org.apache.commons.lang3.StringUtils.isNotBlank(ani)){
    			
    			contacts.setMobileno(ani);
    			contacts.setPhone(ani);
    		}
    		contacts.setTouchtime(new Date());
    		contacts.setOrgi(super.getOrgi(request));
    		contacts.setCreater(super.getUser(request).getId());
    		contacts.setCreatetime(new Date());
    		contactsRes.save(contacts) ;
    		workOrders.setCusid(contacts.getId());
    		
    		contactsid = contacts.getId() ;
    		
    		if(!StringUtils.isBlank(dataid)) {
    			AgentService agentService = agentServiceRepository.findByIdAndOrgi(dataid, super.getOrgi(request)) ;
    			if(agentService!=null) {
    				AgentUserContacts agentUserContacts = new AgentUserContacts() ;
    				agentUserContacts.setAppid(agentService.getAppid());
    				agentUserContacts.setChannel(agentService.getChannel());
    				agentUserContacts.setContactsid(contactsid);
    				agentUserContacts.setUserid(agentService.getUserid());
    				agentUserContacts.setCreater(super.getUser(request).getId());
    				agentUserContacts.setOrgi(super.getOrgi(request));
    				agentUserContacts.setCreatetime(new Date());
    				agentUserContactsRes.save(agentUserContacts) ;
    			}
    		}
    	}
		String orderNo = String.valueOf(WorkOrdersUtils.getWorkOrderNumber(super.getOrgi(request)));
		List<WorkOrders> orderNoList = null;
		do {
			orderNoList	= workOrdersRes.findByOrdernoAndOrgi(orderNo,super.getOrgi(request));
			if(orderNoList != null && orderNoList.size() > 0){
				orderNo = String.valueOf(WorkOrdersUtils.getWorkOrderNumber(super.getOrgi(request)));
			}
		}while (orderNoList != null && orderNoList.size() > 0);


		workOrders.setOrderno(orderNo);

    	if(!StringUtils.isBlank(workOrders.getAccuser())){
    		workOrders.setAssigned(true) ;
    	}else{
    		workOrders.setAssigned(false) ;
    	}
    	
    	processAttachmentFile(files, workOrders, request, workOrders.getId(), workOrders.getId());
    	
    	workOrdersRes.save(workOrders) ;
    	if(!StringUtils.isBlank(source)) {
    		if(source.equals("callcenter")) {
    			view = request(super.createRequestPageTempletResponse("redirect:/apps/softphone/workorders.html?contactsid="+contactsid)) ;
    		}else if(source.equals("callout")) {
    			view = request(super.createRequestPageTempletResponse("redirect:/apps/callout/softphone/workorders.html?dataid="+workOrders.getDataid())) ;
    		}else if(source.equals("agent")) {
    			view = request(super.createRequestPageTempletResponse("redirect:/agent/workorders/list.html?dataid="+workOrders.getDataid()+"&contactsid="+contactsid)) ;
    		}
    	}
    	return view;
    }
    /**
     * 统一查询 工单详情
     * @param map
     * @param request
     * @param id
     */
    public WorkOrders workOrderDetail(ModelMap map , HttpServletRequest request , String id) {
    	WorkOrders workOrders = null ;
    	if(!StringUtils.isBlank(id)) {
	    	workOrders = workOrdersRes.findByIdAndOrgi(id,super.getOrgi(request)) ;
	    	if(workOrders!=null){
	    		map.addAttribute("workOrders", workOrders);
	    		
	    		if(!StringUtils.isBlank(workOrders.getWotype())){
	    			WorkOrderType workOrderType = workOrderTypeRes.findByIdAndOrgi(workOrders.getWotype(), super.getOrgi(request)) ;
	    			map.addAttribute("workOrderType", workOrderType);
	    		}
	    		
	    		workOrders.setUser(userRes.findByIdAndOrgi(workOrders.getCreater() , super.getOrgiByTenantshare(request)));
	    		
	    		if(!StringUtils.isBlank(workOrders.getCusid())){
	    			workOrders.setContacts(contactsRes.findByIdAndOrgi(workOrders.getCusid(),super.getOrgi(request)));
	    		}
	    		
	    		if(!StringUtils.isBlank(workOrders.getInitiator())){
	    			map.addAttribute("initiator", userRes.findByIdAndOrgi(workOrders.getInitiator(),super.getOrgi(request)));
	    		}
	    		
	    		if(!StringUtils.isBlank(workOrders.getAccuser())){
	    			workOrders.setCurrent(userRes.findByIdAndOrgi(workOrders.getAccuser(),super.getOrgi(request)));
	    			map.addAttribute("current",workOrders.getCurrent());
	    		}
	    		
	    		if(workOrders.getContacts()!=null){
	    			map.addAttribute("contacts",workOrders.getContacts());
	    		}
	    		
	    		if(!StringUtils.isBlank(workOrders.getAccdept())){
	    			map.addAttribute("userList", userRes.findByOrganAndDatastatusAndOrgi(workOrders.getAccdept() , false , super.getOrgiByTenantshare(request))) ;
	    		}
	    		map.addAttribute("attachmentFileList", attachementRes.findByDataidAndOrgi(workOrders.getId(), super.getOrgi(request))) ;
	    	}
	    	map.addAttribute("workOrderTypeList", workOrderTypeRes.findByOrgi(super.getOrgi(request))) ;
	    	map.addAttribute("organList",getOrgans(request)) ;
	    	countWorkOrder(map, request);
    	}
    	return workOrders ;
    }
    
    /**
     * 统计数据
     * @param map
     * @param request
     * @param id
     */
    public void countWorkOrder(ModelMap map , HttpServletRequest request) {
    	BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    	
    	BoolQueryBuilder myBuilder = QueryBuilders.boolQuery();
    	myBuilder.must(termQuery("creater" , super.getUser(request).getId())) ;
    	boolQueryBuilder.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	boolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request))) ;
    	boolQueryBuilder.must(myBuilder) ;
    	
    	Page<WorkOrders> my = workOrdersRes.countById(boolQueryBuilder, null, false, null , 1, super.getPs(request),null) ;
    	
    	boolQueryBuilder = QueryBuilders.boolQuery();
    	
    	myBuilder = QueryBuilders.boolQuery();
    	myBuilder.must(termQuery("accuser" , super.getUser(request).getId())) ;
    	boolQueryBuilder.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	boolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request))) ;
    	boolQueryBuilder.must(myBuilder) ;
    	   	
    	Page<WorkOrders> waite = workOrdersRes.countById(boolQueryBuilder, null, false, null , 1, super.getPs(request),null) ;
    	
    	
    	boolQueryBuilder = QueryBuilders.boolQuery();
    	
    	myBuilder = QueryBuilders.boolQuery();
    	boolQueryBuilder.must(termQuery("assigned" , false)) ;
    	
    	boolQueryBuilder.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	boolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request))) ;
    	
    	BoolQueryBuilder accBuilder = QueryBuilders.boolQuery();
    	if(!org.apache.commons.lang3.StringUtils.isBlank(super.getUser(request).getOrgan())) {
    		accBuilder.should(termQuery("accdept" , super.getUser(request).getOrgan()));//受理部门
    	}
    	accBuilder.should(termQuery("accuser" , super.getUser(request).getId()));//受理人
    	accBuilder.should(termQuery("creater" , super.getUser(request).getId()));//工单创建人
    	boolQueryBuilder.must(accBuilder) ;
    	
    	boolQueryBuilder.must(myBuilder) ;
    	
    	Page<WorkOrders> notassigned = workOrdersRes.countById(boolQueryBuilder, null, false, null , 1, super.getPs(request),null) ;
    	
    	boolQueryBuilder = QueryBuilders.boolQuery();
    	
    	boolQueryBuilder.mustNot(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	boolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request))) ;
    	Page<WorkOrders> fav = workOrdersRes.findByCreater(boolQueryBuilder, true , false, null, super.getUser(request).getId(),  new PageRequest(1, super.getPs(request))) ;
 
    	boolQueryBuilder = QueryBuilders.boolQuery();
    	
    	myBuilder = QueryBuilders.boolQuery();
    	
    	boolQueryBuilder.must(termQuery("status" , UKDataContext.WORKORDERS_CLOSED_STATUS)) ;
    	boolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request))) ;
    	boolQueryBuilder.must(myBuilder) ;
    	Page<WorkOrders> closed = workOrdersRes.countById(boolQueryBuilder, null, false, null , 1, super.getPs(request),null) ;
    	
    	if(UKDataContext.model.get("workflow") !=null) {
	    	org.snaker.engine.access.Page<WorkItem> wfpage = new org.snaker.engine.access.Page<WorkItem>(super.getPs(request));
			wfpage.setPageNo(1);
			wfpage.setPageSize(1);
			facets.getEngine().query().getWorkItems(wfpage, new QueryFilter().setProcessType(UKDataContext.BpmType.WORKORDERS.toString()).setOperators(new String[]{super.getUser(request).getId() , super.getUser(request).getOrgan()})) ;
	
			map.addAttribute("workflow", wfpage.getTotalCount()) ;
    	}
    	map.addAttribute("mycount", my.getTotalElements()) ;
    	map.addAttribute("wait", waite.getTotalElements()) ;
    	map.addAttribute("notassigned", notassigned.getTotalElements()) ;
    	map.addAttribute("fav", fav.getTotalElements()) ;
    	map.addAttribute("closed", closed.getTotalElements()) ;
    }
}